package io.github.uicdb.liba.api.register;

import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.SlotItemHandler;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.jetbrains.annotations.Nullable;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.atomic.AtomicReference;

@ParametersAreNonnullByDefault
@SuppressWarnings("unused")
public class LazyMenu<T extends BlockEntity> extends LazyMenuBase {

    protected final BlockPos blockPos;
    protected final T blockEntity;

    @SuppressWarnings("unchecked")
    public LazyMenu(@Nullable MenuType<?> pMenuType, int pContainerId, Inventory playerInv, FriendlyByteBuf extraData) {
        super(pMenuType, pContainerId,playerInv,extraData);
        this.blockPos = extraData.readBlockPos();
        this.blockEntity = (T) level.getBlockEntity(blockPos);
    }

    public BlockPos getBlockPos() {
        return blockPos;
    }

    public BlockEntity getBlockEntity() {
        return blockEntity;
    }



    /**
     * @return 屏幕是否能够开启
     */
    @Override
    public boolean stillValid(@Nonnull Player player) {
        return stillValid(ContainerLevelAccess.create(this.level, this.blockPos), this.player, this.level.getBlockState(this.blockPos).getBlock());
    }

    /**
     * 将ItemHandler的某个格子转化为slot
     *
     * @param index 格子索引
     * @param x     屏幕坐标X
     * @param y     屏幕坐标Y
     * @return SlotItemHandler，可用于addSlotBox
     */
    public SlotItemHandler newSlot(int index, int x, int y) {
        AtomicReference<SlotItemHandler> result = new AtomicReference<>();
        blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(iItemHandler -> {
            result.set(newSlot(iItemHandler,index,x,y));
        });
        return result.get();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (!(o instanceof LazyMenu<?> lazyMenu)) return false;

        return new EqualsBuilder().append(playerInv, lazyMenu.playerInv).append(extraData, lazyMenu.extraData).append(player, lazyMenu.player).append(getBlockPos(), lazyMenu.getBlockPos()).append(level, lazyMenu.level).append(getBlockEntity(), lazyMenu.getBlockEntity()).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37).append(playerInv).append(extraData).append(player).append(getBlockPos()).append(level).append(getBlockEntity()).toHashCode();
    }

    @Override
    public String toString() {
        return "LazyMenu{" +
                "playerInv=" + playerInv +
                ", extraData=" + extraData +
                ", player=" + player +
                ", blockPos=" + blockPos +
                ", level=" + level +
                ", blockEntity=" + blockEntity +
                '}';
    }


    @FunctionalInterface
    public interface LazyMenuType<T extends AbstractContainerMenu> {
        T create(@Nullable MenuType<?> pMenuType, int pContainerId, Inventory playerInv, FriendlyByteBuf extraData);
    }
}
